#pragma once
#include <unistd.h>
#include <iostream>
#include <string>
#include <strings.h>
#include "Logger.hpp"
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <errno.h>
#include <cstdlib>


//客户端要知道：服务端的ip/port 
class UdpClient
{
    public:
    UdpClient(const std::string& ip,uint16_t port):_sockfd(-1),_server_ip(ip),_server_port(port),_flag(false)
    {}

    void Init()
    {
        _sockfd = socket(AF_INET,SOCK_DGRAM,0);
        if(_sockfd < 0)
        {
            LOG(LogLevel::FATAL) << "create client socket error";
            exit(errno);
        }
        LOG(LogLevel::INFO) << "create client socket success";
    }
    void Start()
    {
        _flag = true;
        //填充相关服务端信息
        struct sockaddr_in server;
        socklen_t len = sizeof(server);
        server.sin_addr.s_addr = inet_addr(_server_ip.c_str());
        server.sin_port = htons(_server_port);
        server.sin_family = AF_INET;
        while(_flag)
        {
            //客户端：发信息，再读信息
            std::cout << "Please Enter# ";
            std::string buffer;
            std::getline(std::cin,buffer);
            int n = sendto(_sockfd,buffer.c_str(),buffer.size(),0,(struct sockaddr*)&server,len);
            if(n < 0)
            {
                LOG(LogLevel::FATAL) << "client sendto error";
                exit(errno);
            }
            // std::cout << n << std::endl;
            // struct sockaddr_in local;
            // socklen_t len = sizeof(local);
            // getsockname(_sockfd, (struct sockaddr*)&local, &len);
            // printf("客户端真实 IP: %s:%d\n", inet_ntoa(local.sin_addr), ntohs(local.sin_port));
            
            //接收服务端传回的信息
            char buff[1024] = {0};
            int sz = recvfrom(_sockfd,buff,sizeof(buff),0,nullptr,nullptr);
            if(sz < 0)
            {
                LOG(LogLevel::FATAL) << "client recvfrom error";
                exit(errno);
            }
            buffer[sz] = 0;
            std::cout << buffer << std::endl;
        }
    }

    void Stop()
    {
        _flag = false;
    }
    private:
    int _sockfd;
    std::string _server_ip;
    uint16_t _server_port;
    bool _flag;
};